import React, { Component } from 'react'
import { unmountComponentAtNode } from 'react-dom';

// 引出生命周期
// 生命周期回调函数 <=> 生命周期钩子函数 <=> 生命周期函数 <=> 生命周期钩子
export class Life extends Component {
  state = { opacity: 1 }

  death = () => {
    // 卸载组件
    unmountComponentAtNode(document.getElementById('root'))
  }

  // 组件挂载完毕
  componentDidMount() {
    console.log('componentDidMount~');
    this.timer = setInterval(() => {
      //获取原状态
      let { opacity } = this.state
      //减小0.1
      opacity -= 0.1
      if (opacity <= 0) opacity = 1
      //设置新的透明度
      this.setState({ opacity })
    }, 200);
  }

  // 组件将要卸载
  componentWillUnmount() {
    console.log('componentWillUnmount~');
    // 清除定时器
    clearInterval(this.timer)
  }

  // 初始化渲染、状态更新之后
  render() {
    console.log('render~');
    return (
      <div>
        <h2 style={{ opacity: this.state.opacity }}>React学不会怎么办？</h2>
        <button onClick={this.death}>不活了</button>
      </div>
    )
  }
}

// 生命周期(旧)
export class Count extends Component {

  // 1. constructor
  constructor(props) {
    console.log('Count---constructor~')
    super(props)
    // 初始化状态
    this.state = {
      count: 0
    }
  }

  // 加1按钮的回调
  add = () => {
    const { count } = this.state
    this.setState({
      count: count + 1
    })
  }

  //卸载组件按钮的回调
  death = () => {
    unmountComponentAtNode(document.getElementById('root'))
  }

  //强制更新按钮的回调
  force = () => {
    this.forceUpdate()
  }

  // 2. 组件将要挂载
  componentWillMount() {
    console.log('Count---componentWillMount~')
  }

  // 3. render
  render() {
    console.log('Count---render~')
    const { count } = this.state
    return (
      <div>
        <img src="assets/image/react生命周期(旧).png" alt="" />
        <h2>当前求和为：{count}</h2>
        <button onClick={this.add}>点我+1</button>
        <button onClick={this.death}>卸载组件</button>
        <button onClick={this.force}>不更改任何状态中的数据，强制更新一下</button>
      </div>
    )
  }

  // 4. componentDidMount
  componentDidMount() {
    console.log('Count---componentDidMount~')
  }

  // 5. 将要卸载
  componentWillUnmount() {
    console.log('Count---componentWillUnmount~')
  }

  // 第二条线-更新-开启 由 setState 触发
  // 控制组件更新的阀门 - 必须返回bool
  shouldComponentUpdate() {
    console.log('Count---shouldComponentUpdate~')
    return true
  }

  // 组件将要更新
  componentWillUpdate() {
    console.log('Count---componentWillUpdate~')
  }

  componentDidUpdate() {
    console.log('Count---componentDidUpdate~')
  }

  // 特殊：强制更新！！可以跳过阀门 由 forceUpdate 触发

}

// 父子组件 —— 生命周期
// 父组件A
export class A extends Component {
  //初始化状态
  state = { carName: '奔驰' }

  changeCar = () => {
    this.setState({ carName: '奥拓' })
  }

  render() {
    return (
      <div>
        <img src="assets/image/react生命周期(旧).png" alt="" />
        <div>我是A组件</div>
        <button onClick={this.changeCar}>换车</button>
        <B carName={this.state.carName} />
      </div>
    )
  }
}

// 子组件B
export class B extends Component {
  // 组件将要接收新的props的钩子
  // 第一次接收的时候不调, 新的props过来时才调用
  componentWillReceiveProps(props) {
    console.log('B---componentWillReceiveProps~', props);
  }

  // 控制组件更新的“阀门”
  shouldComponentUpdate() {
    console.log('B---shouldComponentUpdate~');
    return true
  }
  // 组件将要更新的钩子
  componentWillUpdate() {
    console.log('B---componentWillUpdate~');
  }

  // 组件更新完毕的钩子
  componentDidUpdate() {
    console.log('B---componentDidUpdate~');
  }

  render() {
    console.log('B---render~');
    return (
      <div>我是B组件，接收到的车是: {this.props.carName}</div>
    )
  }
}

/*
  1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
            1.	constructor()
            2.	componentWillMount()
            3.	render()
            4.	componentDidMount() =====> 常用
                    一般在这个钩子中做一些初始化的事，例如：开启定时器、发送网络请求、订阅消息
  2. 更新阶段: 由组件内部this.setSate()或父组件render触发
            1.	shouldComponentUpdate()
            2.	componentWillUpdate()
            3.	render() =====> 必须使用的一个
            4.	componentDidUpdate()
  3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
            1.	componentWillUnmount()  =====> 常用
                    一般在这个钩子中做一些收尾的事，例如：关闭定时器、取消订阅消息
*/